package com.css.fxfzdzzh.base.upload;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ZipUtil;
import com.css.fxfzdzzh.base.attachment.entity.AttachmentInfoEntity;
import com.css.fxfzdzzh.base.attachment.service.AttachmentInfoService;
import com.css.fxfzdzzh.base.response.RestResponse;
import com.css.fxfzdzzh.modules.drill.service.DrillService;
import com.css.fxfzdzzh.util.PlatformObjectUtils;
import com.css.fxfzdzzh.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Dbj
 * @date 2022年08月01日  16:40
 * @desc 附件的上传和下载
 */
@RestController
@Slf4j
@RequestMapping("/attachment")
public class AttachmentController {

    @Value("${image.localDir}")
    private String localDir;
    @Resource
    private DrillService drillService;
    @Value("${basicData.url}")
    public String basicDataUrl;
    @Value("${dem.demFilePath}")
    String demFilePath;
    @Value("${dem.demFileDir}")
    String demFileDir;
    @Value("${dem.demFileFolder}")
    String demFileFolder;

    @Autowired
    private AttachmentInfoService attachmentInfoService;
    /**
     * 文件上传
     */
    @PostMapping("/uploadFile")
    public RestResponse uploadFile(List<MultipartFile> file){
        RestResponse restResponse = null;
        if (file.size()==0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if(file.size()>50){
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        for(int i = 0;i<file.size();i++){
            if(!file.get(i).isEmpty()){
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName=multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName,savePath,multipartFile);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(fileName,dateDir,realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if(ObjectUtils.isNotEmpty(attachmentInfoEntities)){
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if(flag==1){
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private String uploadFile(String fileName, String savePath,MultipartFile multipartFile) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        String preFileName = fileName.substring(0,fileName.lastIndexOf("."));
        // .jpg  .pdf  .txt  .docs
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        // 拼文件名  真实的文件名称
        String realFileName = preFileName + "_"  + System.currentTimeMillis() + fileType;
        //判断文件夹是否存在如果不存在则创建
        if(!new File(savePath).exists()){
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }

    private AttachmentInfoEntity buildAttachment(String fileName, String dateDir, String realFileName) {
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(StringUtils.buildPrimaryId());
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath( dateDir + "/" + realFileName);
        attachmentInfoEntity.setFileDirId(localDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    }

    private AttachmentInfoEntity buildTifAttachment(String fileName){
        String id = StringUtils.buildPrimaryId();
        AttachmentInfoEntity attachmentInfoEntity = new AttachmentInfoEntity();
        attachmentInfoEntity.setAttachId(id);
        attachmentInfoEntity.setAttachName(fileName);
        attachmentInfoEntity.setAttachPath(demFileFolder + fileName);
        attachmentInfoEntity.setFileDirId(demFileDir);
        attachmentInfoEntity.setIsValid("1");
        attachmentInfoEntity.setIsCompleted("1");
        return attachmentInfoEntity;
    };
    /**
     * 文件下载
     * @param attachId 附件id
     */
    @GetMapping(value = "/downLoadFile")
    public void downloadFile(@RequestParam("attachId") String attachId) {
        OutputStream os = null;
        InputStream is = null;
        try{
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            String attachPath = attachmentInfoEntity.getAttachPath();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(attachPath)) {
                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                    ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                    assert requestAttributes != null;
                    HttpServletResponse response = requestAttributes.getResponse();
                    assert response != null;
                    response.reset();
                    response.setContentType("application/octet-stream");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(),"UTF-8") + "\"");
                    // 跨域
                    response.setHeader("Access-Control-Allow-Origin", "*");
                    response.setHeader("Access-Control-Allow-Method", "POST,GET");
//                    String name = localDir  + attachPath;
                    String name = attachmentInfoEntity.getFileDirId()  + attachPath;//file、image等路径
                    is = new FileInputStream(new File(name));

                    // PrintWrite pw=response.getWriter();  或
                    os = response.getOutputStream();
                    int flag = 0;
                    while ((flag = is.read()) != -1) {
                      os.write(flag);
                    }
            }
        } catch (Exception e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally{
            try{
                if(is != null){
                    is.close();
                }
                if(os != null){
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 文件下载
     *
     * @param attachIds 附件id
     */
    @GetMapping(value = "/downLoadFiles")
    public void downLoadFiles(@RequestParam("attachId") String attachIds) {
        try {
            List<File> files = new ArrayList<>();
            List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
            for (String attachId : attachIds.split(",")) {
                //根据id和文件名获取真实的放在磁盘上的文件
                AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
                String attachPath = attachmentInfoEntity.getAttachPath();
                if (org.apache.commons.lang3.StringUtils.isNotBlank(attachPath)) {
                    files.add(FileUtil.file(localDir + File.separator + attachPath));
                    attachmentInfoEntities.add(attachmentInfoEntity);
                }
            }
            if (CollectionUtils.isEmpty(files)) {
                return;
            }
            if (files.size() == 1) {
                AttachmentInfoEntity attachmentInfoEntity = attachmentInfoEntities.get(0);
                String attachPath = attachmentInfoEntity.getAttachPath();
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(), "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String name = localDir + File.separator + attachPath;
                try (InputStream is = new FileInputStream(new File(name)); OutputStream os = response.getOutputStream()) {
                    int flag = 0;
                    while ((flag = is.read()) != -1) {
                        os.write(flag);
                    }
                }
            } else {
                File zipFile = FileUtil.file("./temp_" + IdUtil.getSnowflakeNextIdStr() + ".zip");
                ZipUtil.zip(zipFile, false, files.toArray(new File[0]));
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".zip", "UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                try (InputStream is = new FileInputStream(zipFile); OutputStream os = response.getOutputStream()) {
                    int flag = 0;
                    while ((flag = is.read()) != -1) {
                        os.write(flag);
                    }
                }
                zipFile.delete();
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
    }
    /**
     * tif文件下载
     * @param attachId 附件id
     */
    @GetMapping(value = "/downLoadTifFile")
    public void downLoadTifFile(@RequestParam("attachId") String attachId) {
        OutputStream os = null;
        InputStream is = null;
        try{
            //根据id和文件名获取真实的放在磁盘上的文件
            AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
            String attachName = attachmentInfoEntity.getAttachName();
            if (org.apache.commons.lang3.StringUtils.isNotBlank(attachName)) {
                // 防乱码
//                    String name =
//                        new String(realFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
                ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert requestAttributes != null;
                HttpServletResponse response = requestAttributes.getResponse();
                assert response != null;
                response.reset();
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(attachmentInfoEntity.getAttachName(),"UTF-8") + "\"");
                // 跨域
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Method", "POST,GET");
                String name = demFilePath  + attachName + ".tif";
                if(attachName.endsWith(".tif")){
                    name = demFilePath  + attachName;
                }
                is = new FileInputStream(new File(name));

                // PrintWrite pw=response.getWriter();  或
                os = response.getOutputStream();
                int flag = 0;
                while ((flag = is.read()) != -1) {
                    os.write(flag);
                }
            }
        } catch (Exception e){
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally{
            try{
                if(is != null){
                    is.close();
                }
                if(os != null){
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除附件
     * @param map
     * @return
     */
    @PostMapping("/deleteFile")
    public RestResponse deleteFile(@RequestBody Map<String,String> map){
        RestResponse response = null;
        try{
            if(!PlatformObjectUtils.isEmpty(map)){
                boolean res = attachmentInfoService.deleteFile(map);
                if(res){
                    response = RestResponse.succeed("附件删除成功!");
                    response.setMessage("附件删除成功!");
                }

            }else{
                response = RestResponse.fail("附件删除失败! attachId为空!");
            }
        }catch (Exception e){
            log.error("附件删除失败!",e);
            response=RestResponse.fail("附件删除失败!");
        }
        return response;
    }
    /**
     * shp文件上传
     */
    @PostMapping("/uploadShpFile")
    public RestResponse uploadShpFile(List<MultipartFile> file) {
        RestResponse restResponse = null;
        if (file.size() == 0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if (file.size() > 50) {
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        String currTime = System.currentTimeMillis() + "";
        for (int i = 0; i < file.size(); i++) {
            if (!file.get(i).isEmpty()) {
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName = multipartFile.getOriginalFilename();
                    //获取文件上传的本地路径
                    String dateDir = File.separator + "shape" + File.separator + new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = localDir + File.separator + dateDir;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName, savePath, multipartFile, currTime);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildAttachment(getDateFormatFileName(fileName), dateDir, realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if (ObjectUtils.isNotEmpty(attachmentInfoEntities)) {
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if (flag == 1) {
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    /**
     * tif文件上传--坡度文件
     */
    @PostMapping("/uploadTifFile")
    public RestResponse uploadTifFile(List<MultipartFile> file) {
        RestResponse restResponse = null;
        if (file.size() == 0) {
            restResponse = RestResponse.fail("上传失败，请选择文件");
            return restResponse;
        }
        if (file.size() > 50) {
            restResponse = RestResponse.fail("上传失败，请将上传的文件控制在50个以内");
            return restResponse;
        }
        List<String> attachmentInfoIdList = new ArrayList<String>();
        List<AttachmentInfoEntity> attachmentInfoEntities = new ArrayList<>();
        String currTime = System.currentTimeMillis() + "";
        for (int i = 0; i < file.size(); i++) {
            if (!file.get(i).isEmpty()) {
                MultipartFile multipartFile = file.get(i);
                try {
                    //获取文件名称
                    String fileName = multipartFile.getOriginalFilename();
                    //设置名称
                    String preFileName = fileName.substring(0, fileName.lastIndexOf("."));
                    String fileType = fileName.substring(fileName.lastIndexOf("."));
                    preFileName = preFileName.replace("地形地貌（坡度）_","坡度");
                    preFileName = preFileName.replace("地形地貌（坡向）_","坡向");
                    if(preFileName.length()>15){//防止文件名超长
                        fileName = preFileName.substring(0,15)+fileType;
                    }
                    //获取文件上传的本地路径
                    //String dateDir = File.separator + "shape" + File.separator + new SimpleDateFormat("/yyyy/MM/dd").format(new Date());
                    String savePath = demFilePath;
                    //构建文件
                    assert fileName != null;
                    //上传文件
                    String realFileName = uploadFile(fileName, savePath, multipartFile, currTime);
                    //构建实体类
                    AttachmentInfoEntity attachmentInfoEntity = buildTifAttachment(realFileName);
                    attachmentInfoIdList.add(attachmentInfoEntity.getAttachId());
                    attachmentInfoEntities.add(attachmentInfoEntity);
                } catch (Exception e) {
                    e.printStackTrace();
                    restResponse = RestResponse.fail("文件上传失败");
                    return restResponse;
                }
            }
        }
        int flag = 0;
        //保存附件到数据库
        if (ObjectUtils.isNotEmpty(attachmentInfoEntities)) {
            flag = attachmentInfoService.save(attachmentInfoEntities);
        }

        //上传成功返回文件名用于业务实体保存
        if (flag == 1) {
            restResponse = RestResponse.succeed(attachmentInfoEntities);
            restResponse.setMessage("上传成功!");
        } else {
            restResponse = RestResponse.fail("文件上传失败");
        }
        return restResponse;
    }

    private String uploadFile(String fileName, String savePath, MultipartFile multipartFile, String currTime) throws IOException {
        // 获取文件的后缀名
        assert fileName != null;
        String preFileName = fileName.substring(0, fileName.lastIndexOf("."));
        // .jpg  .pdf  .txt  .docs
        String fileType = fileName.substring(fileName.lastIndexOf("."));
        // 拼文件名  真实的文件名称
        String realFileName = preFileName + "_" + currTime + fileType;
        //判断文件夹是否存在如果不存在则创建
        if (!new File(savePath).exists()) {
            new File(savePath).mkdirs();
        }
        File file = new File(savePath, realFileName);
        multipartFile.transferTo(file);
        return realFileName;
    }
    private static String getDateFormatFileName(String fileName) {
        return FileUtil.getPrefix(fileName) + "_" + DateUtil.format(new Date(), "yyyyMMddHHmm") + "." + FileUtil.getSuffix(fileName);
    }
    //基础数据--根据id获取文件信息
    @GetMapping("/findOneById")
    public RestResponse findOneById(@RequestParam String attachId){
        String url = basicDataUrl + "/attachment/details?id=" + attachId;
        return drillService.getJCSJ(url,2);
    }

    //业务数据--根据id获取文件信息
    @GetMapping("/getAttachById")
    public RestResponse getAttachById(@RequestParam String attachId){
        //根据id获取真实的放在磁盘上的文件
        AttachmentInfoEntity attachmentInfoEntity = attachmentInfoService.getAttach(attachId);
        return RestResponse.succeed(attachmentInfoEntity);
    }

    @GetMapping("/getAttachByIds")
    public RestResponse getAttachByIds(@RequestParam String attachId){
        //根据id获取真实的放在磁盘上的文件
        List<AttachmentInfoEntity> attachmentInfoEntityList = attachmentInfoService.getAttachByIds(attachId);
        return RestResponse.succeed(attachmentInfoEntityList);
    }
}
